#ifndef __LUAOBJECT_H__
#define __LUAOBJECT_H__

#include "Lua.h"
#include "LuaImpl.h"
#include "../Common/Ptr.h"

class LuaObject : public PtrClass
{
public:
	LuaObject(CLua* lua);
	LuaObject(CLua* lua,const char* fieldname);
	LuaObject(const LuaObject& obj);
	LuaObject(const LuaObject* obj);
	virtual ~LuaObject();
public:
	template<class T> T Get();
	template<class T> bool Check();
	template<class K> Ptr<LuaObject> Sub(K key);
	int Type();

	bool IterNext(Ptr<LuaObject>& key,Ptr<LuaObject>& val);

public:
	void* operator new(size_t size);
	void operator delete(void* ptr);
private:
	CLua* mLua;
	int mRef;
};

template<class T>
T LuaObject::Get()
{
	CHECKSTACK_BEGIN(mLua,0);
	if(!Check<T>())
	{
		return T();
	}
	mLua->RawGetI(LUA_REGISTRYINDEX,mRef);
	T ret = LuaStack::StackValue<T>::Get(mLua,-1);
	mLua->StackPop(1);
	return ret;
}

template<class T> 
bool LuaObject::Check()
{
	CHECKSTACK_BEGIN(mLua,0);
	mLua->RawGetI(LUA_REGISTRYINDEX,mRef);
	bool b = LuaStack::StackValue<T>::Check(mLua,-1);
	mLua->StackPop(1);
	return b;
}

template<class K> 
Ptr<LuaObject> LuaObject::Sub(K key)
{
	CHECKSTACK_BEGIN(mLua,0);
	mLua->RawGetI(LUA_REGISTRYINDEX,mRef);
	if(!mLua->IsTable(-1))
	{
		mLua->StackPop(1);
		return Ptr<LuaObject>(0);
	}
	LuaStack::StackValue<K>::Push(mLua,key);
	mLua->GetTable(-2);
	if(mLua->IsNil(-1))
	{
		mLua->StackPop(2);
		return Ptr<LuaObject>(0);
	}
	int ref = mLua->Ref(LUA_REGISTRYINDEX);
	if(ref==LUA_REFNIL)
	{
		mLua->StackPop(1);
		return Ptr<LuaObject>(0);
	}
	Ptr<LuaObject> retobj = new LuaObject(mLua);
	if(retobj==0)
	{
		mLua->StackPop(1);
		return Ptr<LuaObject>(0);
	}
	retobj->mRef = ref;
	mLua->StackPop(1);
	return retobj;
}

typedef Ptr<LuaObject> LuaObjPtr;

#endif


